<?php
class ModelField extends Object
{
    public $name;
    public $newName;
    public $type;
    public $formatType;
    public $nullable = true;
    public $isPrimaryKey = false;
    public $default;
    public $caption;
    public $sortOrder;
    public $width;
    public $cropLength;
    public $drilldownUrl;
    public $selectList;
    public $enabled = true;
    public $editable = true;
    public $isFilterable = true;
    public $isSortable = true;
    public $refField;
    public $foreignKey;
    public $autoIncrement = false;
    public $charset;
    public $collation;
    public $position;
    public $afterColumn;
    public $comment;
    public $modelName;
    public $size;
    public $css;
    public $group;
    public $hiddenFilter = false;
    public $filterExact = false;

    const TOP = 'TOP';

    public function ModelField(
        $name,
        $type = null,
        $nullable = true,
        $is_primarykey = false,
        $default = null,
        $auto_increment = null,
        $model_name = null,
        $charset = null,
        $collation = null,
        $comment = null
    )
    {
        $this->name = $this->caption = $name;
        $this->type = $type ? strtolower($type) : 'varchar';
        $this->nullable = $nullable;
        $this->isPrimaryKey = $auto_increment ? true : $is_primarykey;
        $this->autoIncrement = $this->isPrimaryKey && $this->IsNumeric() ? 'AUTO_INCREMENT' : $auto_increment;
        $this->default = $default;
        $this->modelName = $model_name;
        $this->charset = $charset;
        $this->collation = $collation;
        $this->comment = $comment;
    }

    public function IsString()
    {
        $type = $this->type;
        SqlAdapter::StripType($type);
        switch($type)
        {
            case 'char':
            case 'varchar':
            case 'text':
            case 'tinytext':
            case 'mediumtext':
            case 'longtext':
            case AppConfig::GetInstance()->SQL_STRING:
                return true;
        }
        return false;
    }

    public function IsBool()
    {
        return String::ContainsAny('bool, tinyint(1)', $this->type);
    }

    public function IsText()
    {
        $type = $this->type;
        SqlAdapter::StripType($type);
        return $type == 'text';
    }

    public function IsDatetime()
    {
        $type = $this->type;
        SqlAdapter::StripType($type);
        switch($type)
        {
            case 'date':
            case 'time':
            case 'year':
            case 'datetime':
            case 'timestamp':
                return true;
        }
        return false;
    }

    public function IsNumeric()
    {
        $type = $this->type;
        SqlAdapter::StripType($type);
        switch($type)
        {
            case 'int':
            case 'tinyint':
            case 'smallint':
            case 'mediumint':
            case 'bigint':
            case 'float':
            case 'double':
            case 'decimal':
                return true;
        }
        return false;
    }

    public function IsHTML()
    {
        return $this->formatType == VmConfig::GetInstance()->FIELDTYPE_HTML;
    }

    public function SetForeignKey($foreignkey)
    {
        $this->foreignKey = $foreignkey;
    }

    public function LoadView($view_id)
    {
        $item = VmFieldModel::GetInstance()->GetByViewIdAndName($view_id, $this->name);
        if (!$item) return;

        $this->caption      = $item['caption'];
        $this->editable     = $item['editable'];
        $this->enabled      = $item['enabled'];
        $this->sortOrder    = $item['sort_order'];
        $this->refField     = $item['ref_field'];
        $this->cropLength   = $item['crop_length'];
        $this->width        = $item['width'];
        $this->drilldownUrl = $item['drilldown_url'];
        $this->css          = $item['css'];
        $this->group        = $item['group'];
        $this->SetFormatType($item['fieldtype_id']);
    }

    public function SetFormatType($format_type)
    {
        $this->formatType = $format_type;
        if ($this->IsSelectBox() || $this->IsTreeSelect())
            $this->selectList = $this->GetSelectList();
    }

    public function SetSelectBox()
    {
        $this->SetFormatType(VmConfig::GetInstance()->FIELDTYPE_SELECT);
    }

    public function SetGridSelect()
    {
        $this->SetFormatType(VmConfig::GetInstance()->FIELDTYPE_GRID_SELECT);
    }

    protected function GetSelectList()
    {
        if ($this->foreignKey)
        {
            $ref_model = Model::GetInstanceByName($this->foreignKey->table);
            $id = $this->foreignKey->field;
            $name = $this->refField ? $this->refField : $id;
            $fields = $id == $name ? $id : "$id, $name";
            $list = $ref_model->Find(null, $fields, $name, 1000);
            return Set::Combine($list, $id, $name);
        }
        else
        {
            $model = Model::GetInstanceByName($this->modelName);
            $items = $model->FindDistinct($this->name);
            return Set::Combine($items, $this->name);
        }
    }

    public function IsSelectBox()
    {
        return $this->formatType == VmConfig::GetInstance()->FIELDTYPE_SELECT;
    }

    public function IsGridSelect()
    {
        return $this->formatType == VmConfig::GetInstance()->FIELDTYPE_GRID_SELECT;
    }

    public function IsCurrency()
    {
        return $this->formatType == VmConfig::GetInstance()->FIELDTYPE_CURRENCY;
    }

    public function IsDatePicker()
    {
        return $this->formatType == VmConfig::GetInstance()->FIELDTYPE_DATEPICKER;
    }

    public function IsTreeSelect()
    {
        return $this->formatType == VmConfig::GetInstance()->FIELDTYPE_TREE_SELECT;
    }

    public function GetSql()
    {
        $rename = $this->GetSqlNewname();
        $after = $this->GetSqlAfterColumn();
        $notnull = $this->GetSqlNotnull();
        $auto_increment = $this->GetSqlAutoIncrement();
        $default = $this->GetSqlDefault();
        $charset = $this->GetSqlCharset();
        $collation = $this->GetSqlCollation();
        $comment = $this->GetSqlComment();
        return "`{$this->name}` $rename {$this->type} $charset $collation $notnull $default $auto_increment $comment $after";
    }

    public function GetSqlAfterColumn()
    {
        if ($this->afterColumn == self::TOP)
            return 'FIRST';
        else
            return $this->afterColumn ? "AFTER `{$this->afterColumn}`" :  null;
    }

    protected function GetSqlNewname()
    {
        return $this->newName ? "`{$this->newName}`" : null;
    }

    public function GetUpdateSql()
    {
        $column = $this->GetSql();
        $primary_key = $this->GetSqlPrimaryKey();
        return ($this->newName ? 'CHANGE' : 'MODIFY') . " COLUMN $column $primary_key";
    }

    public function GetSqlPrimaryKey()
    {
        if ($this->autoIncrement && !$this->isPrimaryKey)
            return ", ADD PRIMARY KEY (`{$this->name}`)";
    }

    protected function GetSqlComment()
    {
        return $this->comment ? "COMMENT '{$this->comment}'" : null;
    }

    protected function GetSqlCharset()
    {
        return $this->charset ? "CHARACTER SET {$this->charset}" : null;
    }

    protected function GetSqlCollation()
    {
        return $this->collation ? "COLLATE {$this->collation}" : null;
    }

    protected function GetSqlNotnull()
    {
        return $this->nullable ? null : 'NOT NULL';
    }

    protected function GetSqlDefault()
    {
        return is_null($this->default) || $this->autoIncrement ? null : "DEFAULT '{$this->default}'";
    }

    protected function GetSqlAutoIncrement()
    {
        return $this->autoIncrement ? 'AUTO_INCREMENT' : null;
    }

    public function GetSqlName()
    {
        return $this->modelName ? $this->modelName.'.'.$this->name : $this->name;
    }

    public function GetSortOrder()
    {
        return $this->sortOrder ? $this->sortOrder : $this->position;
    }

    public function IsHtmlEditor()
    {
        return $this->formatType == VmConfig::GetInstance()->FIELDTYPE_HTMLEDITOR;
    }
}
?>
